﻿using System;
using System.Collections.Generic;
using System.Data;
using System.Data.Entity;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using PessModel;
using System.IO;
using System.Web.Security;
using System.Reflection;
using DynamicQueryLib;
using LinqKit;
using PessMvc.Models;
using System.Diagnostics;
using System.Web.UI.WebControls;
using System.Web.UI;
using System.Text;
using DoddleReport;
using DoddleReport.Web;
using System.Collections;
using System.Globalization;
using System.Resources;
using System.Web.Profile;
using PessMvc.Helpers;
using LinqToExcel;
using LinqToExcel.Domain;
using PessMvc.Lib;
using Ionic.Zip;
using System.Data.Entity.Validation;
using System.Web.Script.Serialization;

namespace PessMvc.Controllers
{
    [Authorize]
    [NotNeedToChangePassword]
    public class ArchiveController : Controller
    {
        private PESSEntities db;
        private IArchiveBL ibl;

        public ArchiveController()
        {
            ibl= new ArchiveBL(this.ModelState);
            db = new PESSEntities();
        }
        //
        // GET: /Archive/

        [Authorize(Roles="Admin")]
        public ActionResult AcceptedProposals()
        {
            var results=db.AcceptedProposals();
            return View(results);
        }

        [Authorize(Roles="Admin,ExpertJudge,Editor,Chair")]
        public ActionResult Index(int activityID, int subjectID=-1,string keyword="",int page=1,int archiveID=-1, int round=-1)//return to the correct page
        {
            if (User.IsInRole("ExpertJudge") && !Utility.IsExpertJudgePwdChanged(User.Identity.Name))
            {
                return RedirectToAction("ChangePasswordandQA","Account");
            }
            return View(PrepareArchiveList(activityID, subjectID, keyword, page, archiveID, "proposal",round));
        }


        [Authorize(Roles = "Admin,ExpertJudge,Editor,Chair")]
        public ActionResult PaperIndex(int activityID, int subjectID = -1, string keyword = "", int page = 1, int archiveID = -1, int round=-1)//return to the correct page
        {
            if (User.IsInRole("ExpertJudge") && !Utility.IsExpertJudgePwdChanged(User.Identity.Name))
            {
                return RedirectToAction("ChangePasswordandQA","Account");
            }
            return View(PrepareArchiveList(activityID,subjectID,keyword,page,archiveID,"paper",round));
        }

        private ArchivesModel PrepareArchiveList(int activityID, int subjectID = -1, string keyword = "", int page = 1, int archiveID = -1, string mode="proposal", int round=0)
        {
            

            ViewData["ActivityID"] = activityID;
            ViewBag.SubjectID = new SelectList(db.Subjects.Where(s => s.ActivityID == activityID), "ID", "Name");
            ViewBag.SelectedSubjectID = subjectID;

            var activity = db.Activities.Find(activityID);
            ViewBag.IsArchiveModificationAllowed = Utility.IsArchiveModificationAllowed(activity, new ModelStateDictionary());//Don't want to show error message.
            ViewBag.HideArchiveDetails = activity.HideArchiveDetails;
            ViewBag.IsScoreInputAllowed = Utility.IsScoreInputAllowed(activity, new ModelStateDictionary());
            ViewBag.IsPaperReviewAllowed = Utility.IsPaperReviewAllowed(activity, new ModelStateDictionary());

            List<ReviewRecord> reviewHistory = null;
            List<ReviewRecord> paperReviewHistory = null;
            IQueryable<Archive> archives;
            string userName = Membership.GetUser().UserName;
            if (keyword.Trim() == "")//not searching by keyword
            {
                archives = db.Archives.Include(a => a.Subject).Include(a => a.County).Where(a => a.Subject.ActivityID == activityID);


                if (Roles.IsUserInRole(Membership.GetUser().UserName, "ExpertJudge"))
                {
                    //var exptSubjectIDs = from eg in db.ExpertJudges.Find(userName).ExpertGroups//.Subject.ID;
                    //                     select eg.SubjectID;
                    //archives = archives.Where(a => exptSubjectIDs.Contains(a.SubjectID));
                    var groups = db.ExpertJudges.Find(userName).ExpertGroups;
                    IEnumerable<int> exptGroupIDs = new List<int>();
                    if (groups != null)
                    {
                        exptGroupIDs = from eg in db.ExpertJudges.Find(userName).ExpertGroups//.Subject.ID;
                                           select eg.ID;
                    }                    
                    archives = archives.Where(a => exptGroupIDs.Contains((int)(a.ExpertGroupID == null ? -1 : a.ExpertGroupID)));
                    if (mode == "paper")
                    {
                        //for reviewers, only list underreview papers
                        archives = archives.Where(a => exptGroupIDs.Contains((int)(a.ExpertGroupID == null ? -1 : a.ExpertGroupID))&&a.PaperStatus>1);
                    }
                    //if(Utility.IsScoreInputAllowed(activity,new ModelStateDictionary()) && mode=="proposal")
                    //{
                    //    archives = archives.Where(a => a.ID == -1000);
                    //}
                    //else if (Utility.IsPaperReviewAllowed(activity, new ModelStateDictionary()) && mode == "paper")
                    //{
                    //    archives = archives.Where(a => a.ID == -1000);
                    //}
                }
                else if (mode == "paper")
                {
                    archives = archives.Where(a => a.Status == 4&&a.PaperStatus>0); //for paper, only list accepted proposals for chair
                }
                else
                {
                    if (subjectID >= 0)
                    {
                        archives = archives.Where(a => a.SubjectID == subjectID);
                    }
                }
                if (Roles.IsUserInRole("CountyAdmin"))
                {
                    ProfileBase profile = ProfileBase.Create(userName);
                    string countyCode = (string)profile["CountyCode"];
                    archives = archives.Where(a => a.CountyCode.Trim() == countyCode.Trim());
                }
                if(Roles.IsUserInRole("Editor")&&mode=="paper")
                {
                    archives = archives.Where(a => a.PaperStatus > 2);
                }

            }
            else//search by keyword
            {
                if (Roles.IsUserInRole("ExpertJudge"))
                {
                    archives = Search(activityID, keyword, activity.HideArchiveDetails);
                }
                else
                {
                    archives = Search(activityID, keyword, false);
                }
            }
            archives = archives.Where(a => a.Status > 1);//exclude deleted and editing proposal
            archives = archives.OrderBy(a => a.SubjectID).ThenBy(a => a.CountyCode);
            if (round > 0)
            {
                string rs = round.ToString();
                archives = archives.Where(a => a.GradeLevel== rs);
            }

            //Find the review history.
            if (Roles.IsUserInRole(Membership.GetUser().UserName, "ExpertJudge"))
            {
                reviewHistory = (from s in db.Scores
                                 select new ReviewRecord { ArchiveID = s.ArchiveID, ExpertSN = s.ExpertJudgeSerialNumber }).Union(
                                from c in db.ExpertComments
                                select new ReviewRecord { ArchiveID = c.ArchiveID, ExpertSN = c.ExpertSerialNumber }
                              ).Where(t => t.ExpertSN == userName).Distinct().ToList();
                paperReviewHistory = (from s in db.PaperScores
                                      select new ReviewRecord { ArchiveID = s.ArchiveID, ExpertSN = s.ExpertJudgeSerialNumber }).Union(
                                from c in db.PaperComments
                                select new ReviewRecord { ArchiveID = c.ArchiveID, ExpertSN = c.ExpertSerialNumber }
                              ).Where(t => t.ExpertSN == userName).Distinct().ToList();
            }

            PageInfo pageInfo = new PageInfo();
            pageInfo.TotalItems = archives.Count();
            pageInfo.ItemsPerPage = 50;
            if (archiveID >= 1)
            {
                int index = archives.ToList().Select((a, i) => new { Archive = a, Index = i }).First(a => a.Archive.ID == archiveID).Index;
                pageInfo.CurrentPage = index / pageInfo.ItemsPerPage + 1;
            }
            else
            {
                pageInfo.CurrentPage = page;
            }

            ArchivesModel model = new ArchivesModel(archives
                .Skip((pageInfo.CurrentPage - 1) * pageInfo.ItemsPerPage).Take(pageInfo.ItemsPerPage)//paging
                .ToList());
            model.PageInfo = pageInfo;
            model.ActivityID = activityID;
            model.SubjectID = subjectID;
            model.Keyword = keyword;
            model.ReviewHistory = reviewHistory;
            model.PaperReviewHistory = paperReviewHistory;
            model.ExpertGroups = db.ExpertGroups.Where(g => g.Subject.ActivityID == activityID).ToList();

            return model;
        }

        private IQueryable<Archive> Search(int activityID, string keyword, bool? hideArchiveDetails)
        {
            keyword = keyword.Trim();
            //Get string type properties from Archive
            var properties= GetArchiveProperties<Archive>();
            if (hideArchiveDetails==true)
            {
                properties = properties.Where(p =>
                    p.Name.Equals("SerialNumber")||p.Name.Equals("ProjectTitle")
                    ).ToList();
            }
            //Prepare the filters
            List<DynamicQueryLib.Filter> filterList = new List<DynamicQueryLib.Filter>();
            for (int i=0;i<properties.Count;i++)// var prop in properties)
            {
                DynamicQueryLib.Filter f = new DynamicQueryLib.Filter();
                if (i == 0)
                {
                    f.Connector = FilterConnectorType.AND;//the first connector must be AND, otherwise, you get a true
                }
                else
                {
                    f.Connector = FilterConnectorType.OR;
                }
                f.PropertyName = properties[i].Name;
                f.PropertyType = typeof(string);
                f.Values.Add(keyword);
                f.Operator = RelationalOperators.Contains;
                filterList.Add(f);
            }
            var predicate = LambdaExpressionHelper<Archive>.CreatePredicate<Archive>(filterList);
            var activityArchives = db.Archives.AsExpandable().Where(a => a.Subject.ActivityID == activityID);
            var archives =activityArchives.Where(predicate);
            archives=archives.Union(activityArchives.Include("Subject").Include("County").Where(a=>a.Subject.Name.Contains(keyword)||a.County.Name.Contains(keyword)));

            //restrict search result according to user role
            string userName = Membership.GetUser().UserName;
            if (Roles.IsUserInRole(userName, "ExpertJudge"))
            {
                var exptGroupIDs = from eg in db.ExpertJudges.Find(userName).ExpertGroups//.Subject.ID;
                                   select eg.ID;
                archives = archives.Where(a => exptGroupIDs.Contains((int)(a.ExpertGroupID == null ? -1 : a.ExpertGroupID)));                                                         
            }

            if (Roles.IsUserInRole("CountyAdmin"))
            {
                ProfileBase profile = ProfileBase.Create(userName);
                string countyCode = (string)profile["CountyCode"];
                archives = archives.Where(a => a.CountyCode.Trim() == countyCode.Trim());
            }
            //return View(archives);
            return archives;
        }

        private List<PropertyInfo> GetArchiveProperties<T>()
        {
            var properties = typeof(T).GetProperties(BindingFlags.DeclaredOnly
                                                           | BindingFlags.Public
                                                           | BindingFlags.Instance)
                                                           .Where(p => p.PropertyType == typeof(string) && p.Name != "CalculatedSerialNumber").ToList();
            return properties;
        }
        //
        // GET: /Archive/Details/5

        public ActionResult Details(int id, int round)
        {
            Archive archive = db.Archives.Find(id);
            if (archive.SerialNumber==null||archive.SerialNumber.Trim() == "")
            {
                archive.SerialNumber = archive.CalculatedSerialNumber;
            }
            if (archive == null)
            {
                return HttpNotFound();
            }
            if (!Utility.IsUserAllowedtoOpenArchive(archive, Membership.GetUser()))
            {
                return HttpNotFound();
            }

            ViewBag.IsArchiveModificationAllowed = Utility.IsArchiveModificationAllowed(archive.Subject.Activity, new ModelStateDictionary());//Don't want to show error message.
            ViewBag.IsScoreInputAllowed = Utility.IsScoreInputAllowed(archive.Subject.Activity, new ModelStateDictionary());//Don't want to show error message.
            ViewBag.HideArchiveDetails = archive.Subject.Activity.HideArchiveDetails;
            ViewBag.SuggestedCategory = new SelectList(db.Counties, "Code", "Name", archive.CountyCode);
            ViewBag.Round = round;
            //ViewBag.ReturnUrl = returnUrl;
            return View(archive);
        }

        public ActionResult DetailsPaper(int id)
        {
            Archive archive = db.Archives.Find(id);
            if (archive.SerialNumber == null || archive.SerialNumber.Trim() == "")
            {
                archive.SerialNumber = archive.CalculatedSerialNumber;
            }
            if (archive == null)
            {
                return HttpNotFound();
            }
            if (!Utility.IsUserAllowedtoOpenArchive(archive, Membership.GetUser()))
            {
                return HttpNotFound();
            }

            ViewBag.IsArchiveModificationAllowed = Utility.IsArchiveModificationAllowed(archive.Subject.Activity, new ModelStateDictionary());//Don't want to show error message.
            ViewBag.IsScoreInputAllowed = Utility.IsScoreInputAllowed(archive.Subject.Activity, new ModelStateDictionary());//Don't want to show error message.
            ViewBag.HideArchiveDetails = archive.Subject.Activity.HideArchiveDetails;
            //ViewBag.ReturnUrl = returnUrl;
            return View(archive);
        }


        /// <summary>
        /// Get Archive data.
        /// </summary>
        /// <param name="archiveID"></param>
        /// <returns></returns>
        [Authorize(Roles="ExpertJudge")]
        [ExpertJudgeInfoComplete]
        public ActionResult Grade(int archiveID)
        {
            var archive = db.Archives.Find(archiveID);
            if (!Utility.IsScoreInputAllowed(archive.Subject.Activity, this.ModelState))
            {
                throw new Exception("Cannot review at this time!");
            }
            //return Details(archiveID);
            ArchiveGradeModel model = new ArchiveGradeModel();
            MembershipUser user = Membership.GetUser();
            if (Roles.IsUserInRole(user.UserName, "ExpertJudge"))
            {
                string expertSerialNumber = user.UserName;//"A1S7PW1";Membership
                var scores = db.sp_GetArchiveExpertScores(expertSerialNumber, archiveID);
                model.Scores = scores;
                model.Archive = db.Archives.Find(archiveID);
                try{
                    ExpertComment comment= model.Archive.ExpertComments.Where(c=>c.ExpertSerialNumber==user.UserName).FirstOrDefault();
                    model.Comment=comment.Comment;
                }
                catch{
                    model.Comment = "";
                }                
            }

            ViewBag.SerialNumber = model.Archive.SerialNumber;
            model.ActivityID = model.Archive.Subject.ActivityID;
            return View(model);
        }
        [HttpPost]
        [Authorize(Roles = "ExpertJudge")]
        public ActionResult Grade(List<sp_GetArchiveExpertScores_Result> scoreList,int archiveID,string comment="")//List<Score> scores,int archiveID)
        {
            Archive archive = db.Archives.Find(archiveID);
            List<Score> scores = (from s in scoreList
                                  select new Score()
                                  {
                                      RuleID = s.ID,
                                      ArchiveID = (int)s.ArchiveID,
                                      ExpertJudgeSerialNumber = s.ExpertJudgeSerialNumber,
                                      Value = s.ScoreValue
                                  }).ToList();
            //Get Current User Name
            string expertSerialNumber = Membership.GetUser().UserName;//"A1S7PW1";

            if (ModelState.IsValid)
            {                
                foreach (var score in scores)
                {
                    score.ExpertJudgeSerialNumber = expertSerialNumber;

                    if (Helpers.Utility.ScoreValueIsLessthanLimit(score))
                    {
                        var pessScore = db.Scores.Find(score.RuleID, score.ArchiveID, expertSerialNumber);
                        if (pessScore == null)
                        {
                            db.Scores.Add(score);
                        }
                        else
                        {
                            pessScore.Value = score.Value;
                            db.Entry(pessScore).State = EntityState.Modified;
                            //db.ObjectStateManager                    
                        }
                        db.SaveChanges();
                        //
                    }
                    else
                    {
                        ModelState.AddModelError(string.Empty, "Score exceeded!");
                        ArchiveGradeModel model = new ArchiveGradeModel();
                        model.Archive = archive;
                        model.Scores = db.sp_GetArchiveExpertScores(User.Identity.Name, archiveID);
                        model.Comment = comment;
                        return View(model);
                    }
                }
                //Save the comment.
                ExpertComment c = db.ExpertComments.Find(User.Identity.Name, archiveID);
                if (c == null)
                {
                    db.ExpertComments.Add(new ExpertComment()
                    {
                        ExpertSerialNumber = User.Identity.Name,
                        ArchiveID = archiveID,
                        Comment = comment.StripHtmlTags()
                    });
                    db.SaveChanges();
                }
                else
                {
                    c.Comment = comment.StripHtmlTags();
                    db.SaveChanges();
                }
            }
            

            //Expert Judge don't really care about the details. So, let them see the index instead.
            //return RedirectToAction("Details", "Archive", new { id = scores.First().ArchiveID });  
            //int archiveID=scores.First().ArchiveID;
            int activityID=db.Archives.Find(archiveID).Subject.ActivityID;
            return RedirectToAction("Index", "Archive", new { activityID = activityID });
        }
        public FileStreamResult GetPDF(int archiveID)
        {
            //1.If there is a pdf file with the same name as archive's SN.
            //2.If there is only one pdf file.
            //3.If there are many pdf files.
            //4.If there is no pdf file.
            string title = "";
            List<Attachment> pdfFiles = db.Attachments
                .Where(a => a.ArchiveID == archiveID).ToList()
                .Where(a => a.Title.FileExtName().ToLower() == "pdf").ToList();
            Archive archive=db.Archives.Find(archiveID);
            if (pdfFiles.Where(p => p.Title.Contains(archive.SerialNumber)).Count() > 0)
            {
                title = pdfFiles.Where(p => p.Title.Contains(archive.SerialNumber)).FirstOrDefault().Title;
            }
            else if(pdfFiles.Count==1)
            {
                title = pdfFiles[0].Title;
            }
            else if (pdfFiles.Count > 1)
            {
                title = pdfFiles.OrderBy(p => p.Title).FirstOrDefault().Title;
            }
            else if (pdfFiles.Count == 0)
            {
                title = "";
            }

            FileStream fs;
            if (title != null && title.Length > 0)
            {
                Attachment attachment = db.Attachments.Find(archiveID, title);
                string fullName = Path.Combine(attachment.FilePath, attachment.Title);//Title is filename
                //byte[] fileBytes = PessMvc.Helpers.Utility.GetFile(fullName);
                //return File(fileBytes, System.Net.Mime.MediaTypeNames.Application.Octet, title);
                fs = new FileStream(fullName, FileMode.Open, FileAccess.Read);
                return File(fs, "application/pdf"); 
            }
            else
            {
                //byte[] fileBytes = new byte[] { };// PessMvc.Helpers.Utility.GetFile(fullName);
                MemoryStream mStream = new MemoryStream(Encoding.Unicode.GetBytes("There is no pdf file to display. Please upload."));
                return File(mStream, "application/text");//"application/pdf");
                
            }
            

            //FileStream fs = new FileStream("d:\\cs.pdf", FileMode.Open, FileAccess.Read);
            //return File(fs, "application/pdf");            
        }
        //
        // GET: /Archive/Create
        [Authorize(Roles = "Author")]
        public ActionResult Create(int activityID)
        {
            ViewBag.ActivityID = activityID;//new SelectList(db.Activities, "ID", "Name");
            ViewBag.SubjectID = new SelectList(db.Subjects.Where(s=>s.ActivityID==activityID), "ID", "Name");
            ViewBag.CountyCode = new SelectList(GetCounties(), "Code", "Name");
            ViewBag.Gender = Utility.GenderSelectList(true);

            return View();
        }
        private IQueryable<County> GetCounties()
        {
            IQueryable<County> counties = null;
            MembershipUser user = Membership.GetUser();
            if (Roles.IsUserInRole(user.UserName, "CountyAdmin"))
            {
                ProfileBase profile = ProfileBase.Create(user.UserName);
                string countyCode = (string)profile["CountyCode"];
                counties = db.Counties.Where(c => c.Code == countyCode);
            }
            else if (Roles.IsUserInRole(user.UserName, "Admin"))
            {
                counties = db.Counties;
            }
            return counties;
        }
        //
        // POST: /Archive/Create
        [Authorize(Roles = "Author")]
        [HttpPost]
        public ActionResult Create(Archive archive,int activityID)
        {
            //if (!ModelState.IsValid)
            //{
            //    return View(archive);
            //}
            //ViewBag.ActivityID = db.Subjects.Find(archive.SubjectID).ActivityID;
            //int acitivityID=(int)ViewBag.ActivityID;
            //archive.Subject = db.Subjects.Find(archive.SubjectID);

            ViewBag.ActivityID = activityID;
            ViewBag.SubjectID = new SelectList(db.Subjects.Where(s => s.ActivityID ==activityID), "ID", "Name", archive.SubjectID);
            ViewBag.CountyCode = new SelectList(GetCounties(), "Code", "Name");
            ViewBag.Gender = Utility.GenderSelectList(archive.Gender);

            int quotaLimit = 0;
            var quota = db.CandidateQuotas.Find(archive.SubjectID, archive.CountyCode);
            if (quota == null) { quotaLimit = 0; }
            else
            {
                quotaLimit = Convert.ToInt32(quota.Quota);
            }
            if (quota!=null&&db.Archives.Where(a => a.CountyCode == quota.CountyCode && a.SubjectID == quota.SubjectID).Count() < quotaLimit)
            {
                //Add archive to database
                if (ModelState.IsValid)
                {
                    //Make sure the previousSN and the current one are of the same county.
                    Archive preArchive=db.Archives.Where(a => a.SerialNumber == archive.PreviousSN).FirstOrDefault();
                    if (archive.PreviousSN==null //Archive has no previous archive.
                        ||preArchive != null && preArchive.CountyCode == archive.CountyCode //Previous archive and the current one belong to the same county.
                        )
                    {
                        try
                        {
                            db.Archives.Add(archive);
                            db.SaveChanges();
                        }
                        catch (DbEntityValidationException e)
                        {
                            foreach (var eve in e.EntityValidationErrors)
                            {
                                Debug.WriteLine("Entity of type \"{0}\" in state \"{1}\" has the following validation errors:",
                                    eve.Entry.Entity.GetType().Name, eve.Entry.State);
                                foreach (var ve in eve.ValidationErrors)
                                {
                                    Debug.WriteLine("- Property: \"{0}\", Error: \"{1}\"",
                                        ve.PropertyName, ve.ErrorMessage);
                                }
                            }
                            throw;
                        }
                        //int activityID = db.Subjects.Where(s => s.ID == archive.SubjectID).SingleOrDefault().ActivityID;

                        //Set archive's serialnumber. If the archive has no specified SerialNumber.
                        db.Entry(archive).Reference(e => e.Subject).Load();
                        if (archive.SerialNumber == null || archive.SerialNumber.Trim() == "")
                        {
                            archive.SerialNumber = string.Format("Y{0}A{1}S{2}V{3}",
                                archive.Subject.Activity.AdminYear.Value.Year,
                                archive.Subject.ActivityID,
                                archive.SubjectID,
                                archive.ID
                            );
                            db.Entry(archive).State = EntityState.Modified;
                            db.SaveChanges();
                        }

                        //存放申报表
                        this.SaveArchiveFormToFolder(activityID, archive);

                        return RedirectToAction("Details", new { id = archive.ID });
                    }
                    else
                    {
                        ModelState.AddModelError(string.Empty, "历史档案不存在，或者非本区档案！");
                    }                    
                }

                //ViewBag.ActivityID = new SelectList(db.Activities, "ID", "Name", archive.Subject.ActivityID);

                return View(archive);
            }
            else
            {
                string errorMsg = "";
                if (quota != null)
                {
                    errorMsg = string.Format("{0}({1}区)的配额已满！", quota.Subject.Name, quota.County.Name);
                }
                else
                {
                    errorMsg = string.Format("配额不存在！");
                }
                ModelState.AddModelError(string.Empty,errorMsg );
                return View(archive);
            }
        }

        //
        // GET: /Archive/Edit/5

        public ActionResult Edit(int id)
        {
            Archive archive = db.Archives.Find(id);

            if (archive.SerialNumber==null||archive.SerialNumber.Trim() == "")
            {
                archive.SerialNumber = archive.CalculatedSerialNumber;
            }

            if (archive == null)
            {
                return HttpNotFound();
            }
            ViewBag.ActivityID = new SelectList(db.Activities, "ID", "Name", archive.Subject.ActivityID);
            ViewBag.SubjectID = new SelectList(db.Subjects.Where(s=>s.ActivityID==archive.Subject.ActivityID) , "ID", "Name", archive.SubjectID);
            ViewBag.Gender = Utility.GenderSelectList(archive.Gender);
            ViewBag.ExpertGroupID = new SelectList(archive.Subject.ExpertGroups, "ID", "CallSign",archive.ExpertGroupID);

            return View(archive);
        }

        //
        // POST: /Archive/Edit/5

        [HttpPost]
        public ActionResult Edit(Archive archive)
        {
            if (ModelState.IsValid)
            {
                db.Entry(archive).State = EntityState.Modified;
                db.SaveChanges();

                //if (archive.SerialNumber == null || archive.SerialNumber.Trim() == "")
                //{
                //    archive.SerialNumber = archive.CalculatedSerialNumber;
                //}
                //db.SaveChanges();

                int activityID = db.Subjects.Find(archive.SubjectID).ActivityID;
                //存放申报表。
                this.SaveArchiveFormToFolder(activityID,archive);

                //return RedirectToAction("Index", new {ActivityID=activityID });
                return RedirectToAction("Details", new { id = archive.ID });
            }
            ViewBag.ActivityID = new SelectList(db.Activities, "ID", "Name", archive.Subject.ActivityID);
            ViewBag.SubjectID = new SelectList(db.Subjects, "ID", "Name", archive.SubjectID);
            ViewBag.Gender = Utility.GenderSelectList(archive.Gender);

            return View(archive);
        }

        /// <summary>
        /// Save the apply form information into a file, then put into the archive folder.
        /// </summary>
        /// <param name="activityID"></param>
        /// <param name="archive"></param>
        private void SaveArchiveFormToFolder(int activityID,Archive archive)
        {
            //
            //1).Get properties from GetArchiveList_Result
            var propertInfos = GetArchiveProperties<GetArchiveList_Result>();
            List<ArchiveProperty> archPropList = new List<ArchiveProperty>();
            for (int i = 0; i < propertInfos.Count; i++)
            {
                archPropList.Add(new ArchiveProperty() { Id = i, Name = propertInfos[i].Name, LocalName = Utility.Translate<PessResources.Archive>(propertInfos[i].Name) });
            }
            //2).Get archive, for report saving.
            var archive1 = db.GetArchiveList(activityID).Where(a => a.SerialNumber == archive.SerialNumber).FirstOrDefault();
            //3).Don't want these properties in the info report.
            string[] excludedProperties = new string[] { "ReviewFeedback", "Conclusion", "ProjectSN", "CountyCode" };
            archPropList = (from p in archPropList
                            where !excludedProperties.Contains(p.Name)
                            select p).ToList();
            foreach (var p in archPropList)
            {
                p.Value = (string)GetPropValue(archive1, p.Name);
            }
            //4).send archPropList to doddle report.
            string path = Path.Combine(Server.MapPath("~/App_Data/Archives/"), activityID.ToString(), archive.ID.ToString());//, "申报表.xls"
            if (!Directory.Exists(path))
            {
                Directory.CreateDirectory(path);
            }
            string fullFilePath = Path.Combine(path, "申报表.xls");
            IReportWriter writer = new DoddleReport.Writers.ExcelReportWriter();
            var report =Utility.CreateReport(archPropList.ToList(), new string[] { "LocalName", "Value" },"申报表",archive.Subject.Activity.Name,archive.TeacherName);
            using (FileStream fs = System.IO.File.Create(fullFilePath))
            {
                writer.WriteReport(report, fs);
            } 
        }

        private object GetPropValue(object src, string propName)
        {
            return src.GetType().GetProperty(propName).GetValue(src, null);
        }
        //
        // GET: /Archive/Delete/5
        [Authorize(Roles = "Author,Admin")]
        public ActionResult Delete(int id = 0)
        {
            Archive archive = db.Archives.Find(id);
            if (archive == null)
            {
                return HttpNotFound();
            }
            return View(archive);
        }

        //
        // POST: /Archive/Delete/5

        [HttpPost, ActionName("Delete")]
        [Authorize(Roles = "Author,Admin")]
        public ActionResult DeleteConfirmed(int id)
        {
            int activityID;
            Archive archive = db.Archives.Find(id);
            activityID = archive.Subject.ActivityID;

            //archive has attachments. delete them.
            RemoveBelongs<Attachment>(archive.Attachments);
            //if (archive.Attachments.Count > 0)
            //{
            //    var attachments=archive.Attachments.ToList();
            //    foreach (var a in attachments)
            //    {
            //        archive.Attachments.Remove(a);
            //    }
            //    db.SaveChanges();
            //}

            //archive has scores. delete them.
            RemoveBelongs<Score>(archive.Scores);
            //if (archive.Scores.Count > 0)
            //{
            //    var scores = archive.Scores.ToList();
            //    foreach (var s in scores)
            //    {
            //        archive.Scores.Remove(s);
            //    }
            //    db.SaveChanges();
            //}

            RemoveBelongs<ExpertComment>(archive.ExpertComments);
            //if (archive.ExpertComments.Count > 0)
            //{
            //    var comments = archive.ExpertComments.ToList();
            //    foreach (var c in comments)
            //    {
            //        archive.ExpertComments.Remove(c);
            //    }
            //    db.SaveChanges();
            //}

            db.Archives.Remove(archive);
            db.SaveChanges();
            
            return RedirectToAction("Index", new {activityID=activityID });
        }

        private void RemoveBelongs<T>(ICollection<T> collection)
        {
            var list = collection.ToList();
            foreach (var item in list)
            {
                collection.Remove(item);
            }
            db.SaveChanges();
        }

        protected override void Dispose(bool disposing)
        {
            db.Dispose();
            base.Dispose(disposing);
        }

        [HttpPost]
        [Authorize(Roles = "Author")]
        public ActionResult UploadAttachment(HttpPostedFileBase file, int archiveID)
        {
            int? activityID=db.Archives.Find(archiveID).Subject.ActivityID;

            // Verify that the user selected a file
            if (file != null && file.ContentLength > 0)
            {
                // extract only the fielname
                var fileName = Path.GetFileName(file.FileName);
                // store the file inside ~/App_Data/uploads folder
                var path = Path.Combine(Server.MapPath("~/App_Data/Archives/"),activityID.ToString(),archiveID.ToString());
                if (!Directory.Exists(path))
                {
                    Directory.CreateDirectory(path);
                }

                file.SaveAs(Path.Combine(path,fileName));                
            }

            return RedirectToAction("Details", "Archive", new { id = archiveID });
        }


        //This action is moved to AttachmentController
        //[Authorize(Roles = "Author")]
        //[HttpPost]
        //public string Upload(HttpPostedFileBase fileData, int archiveID)
        //{
        //    FormsAuthenticationTicket ticket = FormsAuthentication.Decrypt(Request.Form["authCookie"]);
        //    if (ticket != null)
        //    {
        //        var identity = new FormsIdentity(ticket);
        //        if (!identity.IsAuthenticated)
        //        {
        //            return "Not Authenticated";
        //        }
        //    }

        //    // Now parse fileData...

        //    //var fileName = this.Server.MapPath("~/uploads/" + System.IO.Path.GetFileName(file.FileName));
        //    //file.SaveAs(fileName);

        //    int? activityID = db.Archives.Find(archiveID).Subject.ActivityID;

        //    // Verify that the user selected a file
        //    if (fileData != null && fileData.ContentLength > 0)
        //    {
        //        // extract only the fielname
        //        var fileName = Path.GetFileName(fileData.FileName);
        //        // store the file inside ~/App_Data/uploads folder
        //        var path = Path.Combine(Server.MapPath("~/App_Data/Archives/"), activityID.ToString(), archiveID.ToString());
        //        if (!Directory.Exists(path))
        //        {
        //            Directory.CreateDirectory(path);
        //        }
        //        //fileData.SaveAs(Path.Combine(path, fileName));
        //        //Add attachment info to db.
        //        Archive archive = db.Archives.Find(archiveID);

        //        //the following lines are for AECT2005
        //        if (archive.Status==4&&archive.PaperStatus>=6)
        //            fileName = archive.CalculatedSerialNumber + "_Paper_Final" + Path.GetExtension(fileData.FileName);
        //        else
        //            fileName = archive.CalculatedSerialNumber + "_Paper_Attemp" + Path.GetExtension(fileData.FileName);

        //        fileData.SaveAs(Path.Combine(path, fileName));

        //        //1 file version
        //        archive.Attachments.Clear();
        //        FileInfo fileInfo = new FileInfo(Path.Combine(path, fileName));
        //        archive.Attachments.Add(new Attachment { Title = fileName, ArchiveID = archiveID, FilePath = path, TimeStamp = fileInfo.CreationTime, FileSize = (int)(fileInfo.Length / 1024) });

        //        //2 files version
        //        //Attachment doesn't exist.
        //        /*if (archive.Attachments.Where(a => a.Title == fileName).Count() <= 0)
        //        {
        //            FileInfo fileInfo = new FileInfo(Path.Combine(path, fileName));
        //            archive.Attachments.Add(new Attachment { Title = fileName, ArchiveID = archiveID, FilePath = path, TimeStamp = fileInfo.CreationTime, FileSize = (int)(fileInfo.Length / 1024) });
        //        }
        //        else
        //        {//Attachment exits.
        //            Attachment attachment = archive.Attachments.Where(a => a.Title == fileName).SingleOrDefault();
        //            FileInfo fileInfo = new FileInfo(Path.Combine(path, fileName));
        //            attachment.FileSize = (int)(fileInfo.Length / 1024);
        //            attachment.TimeStamp = fileInfo.LastWriteTime;
        //            db.Entry(attachment).State = EntityState.Modified;
        //        }*/

        //        if(archive.PaperStatus<2)
        //            archive.PaperStatus = (int)ArchivePaperStatus.Submitted;
        //        db.Entry(archive).State = EntityState.Modified;
        //        db.SaveChanges();

        //        //send email
        //        using (StreamReader reader = new StreamReader(Server.MapPath("~/App_Data/templates/paperconfirm.txt")))
        //        {
        //            string text = reader.ReadToEnd();
        //            text = text.Replace("[Author]", archive.Name);
        //            text = text.Replace("[Title]", archive.ProjectTitle);
        //            text = text.Replace("[Date]", DateTime.Now.Date.ToString("MM/dd/yyyy"));
        //            // text=text.Replace("[Authors]",);
        //            // text=text.Replace("[Topic]",);
        //            Utility.SendMail("Proceedings Paper Confirmation", text, archive.EMail);
        //        }
        //    }

        //    return "ok";
        //}

        [Authorize(Roles="Admin,Chair")]
        public ActionResult DeleteAttachment(int archiveID, string title)
        {
            var attachment = db.Attachments.Where(a => a.ArchiveID == archiveID && a.Title.Trim() == title.Trim()).FirstOrDefault();
            return View(attachment);
        }

        [HttpPost, ActionName("DeleteAttachment")]
        [Authorize(Roles = "Admin,Chair")]
        [ValidateAntiForgeryToken]
        public ActionResult DeleteDeleteAttachmentConfirmed(int archiveID, string title)
        {
            Attachment attachment = db.Attachments.Find(archiveID, title);
            string fullName = Path.Combine(attachment.FilePath, attachment.Title);//Title is filename
            try
            {
                System.IO.File.Delete(fullName);
            }
            catch { }
            finally
            {
                db.Attachments.Remove(attachment);
                db.SaveChanges();
            }
            return RedirectToAction("Details", "Archive", new { id = archiveID });
        }

        public FileResult Download(int archiveID, string title)
        {
            Attachment attachment=db.Attachments.Find(archiveID,title);
            string fullName=Path.Combine(attachment.FilePath,attachment.Title);//Title is filename
            byte[] fileBytes = PessMvc.Helpers.Utility.GetFile(fullName);
            return File(fileBytes,System.Net.Mime.MediaTypeNames.Application.Octet,title);
        }

        public ActionResult UploadPhoto(HttpPostedFileBase file, int archiveID)
        {
            if (file != null && file.ContentLength > 0)
            {
                var archive = db.Archives.Find(archiveID);
                string fileName = Path.GetFileName(file.FileName);
                int? activityID = db.Archives.Find(archiveID).Subject.ActivityID;
                var path = Path.Combine(Server.MapPath("~/uploads/"), activityID.ToString(), archiveID.ToString());
                if (!Directory.Exists(path))
                {
                    Directory.CreateDirectory(path);
                }

                file.SaveAs(Path.Combine(path, fileName));

                //Add attachment info to db.
                archive.PhotoUrl = fileName;
                db.Entry(archive).State = EntityState.Modified;
                db.SaveChanges();
            }
            return RedirectToAction("Edit", "Archive", new { id = archiveID });
        }

        //public string GetPhotoUrl(int archiveID)
        //{
        //    db.Archives.Find(archiveID);UrlHelper.GenerateContentUrl(
        //}

        /// <summary>
        /// 
        /// </summary>
        /// <param name="archiveID">Current archive id.</param>
        /// <returns></returns>
        public ActionResult PreviousArchives(int archiveID)
        {
            string previousSN=db.Archives.Find(archiveID).PreviousSN;
            ViewBag.ArchiveID = archiveID;
            if(previousSN!=null&&previousSN.Trim()!="")
            {
                List<PreviousArchiveModel> archives = new List<PreviousArchiveModel>();
                FindPrevArchive(previousSN, ref archives);
                //var previousArchive = db.Archives.ToList().Where(a => a.SerialNumber ==previousSN ).FirstOrDefault();                
                return View(archives);
            }
            else
            {
                return View();
            }
        }

        private Archive FindPrevArchive(string serialNumber, ref List<PreviousArchiveModel> archives)
        {
            Archive archive = db.Archives.Where(a => a.SerialNumber.Trim() == serialNumber.Trim()).FirstOrDefault();
            if (archive == null)
            {
                return null;
            }
            archives.Add(new PreviousArchiveModel() { ActivityName = archive.Subject.Activity.Name, ArchiveID = archive.ID, SerialNumber = archive.SerialNumber, TeacherName = archive.TeacherName });

            if (archive.PreviousSN==null||archive.PreviousSN.Trim() == "")//End case
            {                
                return archive;
            }
            else //Recurrive case
            {
                return FindPrevArchive(archive.PreviousSN, ref archives);
            }
        }

        public ActionResult PreviousArchiveDetails(int archiveID, int backtoID)
        {
            var archive = db.Archives.Find(archiveID);
            ViewBag.BackToID = backtoID;
            return View(archive);
        }

        public ActionResult ExportArchiveList(int activityID, List<ArchiveProperty> properties, int subjectID = -1)
        {
            List<string> selectedPropertyList = new List<string>();
            if (properties != null)
            {
                foreach (var p in properties)
                {
                    if (p.IsSelected)
                    {
                        //Debug.WriteLine("Property {0} is selected", p.Name);
                        selectedPropertyList.Add(p.Name);
                    }
                }
            }

            ViewBag.ActivityID = activityID;
            int expertSubjectID = -1;
            if (Roles.IsUserInRole("ExpertJudge")) //Only display expert judge's subject in the dropdown list.
            {
                var expert = db.ExpertJudges.Find(Membership.GetUser().UserName);
                //Not sure how to fix this for now. So I simply set it to -1. Deal with this later.
                expertSubjectID = -1;// expert.ExpertGroup.SubjectID != null ? (int)expert.ExpertGroup.SubjectID : -1;
                ViewBag.SubjectID = new SelectList(db.Subjects.Where(s => s.ActivityID == activityID&&s.ID==expertSubjectID), "ID", "Name");
            }
            else
            {
                ViewBag.SubjectID = new SelectList(db.Subjects.Where(s => s.ActivityID == activityID), "ID", "Name");
            }

            var propertInfos = GetArchiveProperties<GetArchiveList_Result>();
            List<ArchiveProperty> archPropList = new List<ArchiveProperty>();
            for (int i = 0; i < propertInfos.Count; i++)
            {
                archPropList.Add(new ArchiveProperty() { Id = i, Name = propertInfos[i].Name, LocalName = Utility.Translate<PessResources.Archive>(propertInfos[i].Name) });
            }

            ExportArchiveListModel model = new ExportArchiveListModel();
            var archives = db.GetArchiveList(activityID).AsEnumerable();//db.Archives.Where(a => a.Subject.ActivityID == activityID);
            if (subjectID > 0)
            {
                archives = archives.Where(a => a.SubjectID == subjectID);
            }
            if (Roles.IsUserInRole("CountyAdmin"))
            {
                string countyCode = Utility.GetCountyCode();
                archives = archives.Where(a => a.CountyCode == countyCode);
            }
            if (Roles.IsUserInRole("ExpertJudge"))
            {
                archives = archives.Where(a => a.SubjectID == expertSubjectID);
            }
            
            model.Archives = archives;
            model.Properties = archPropList;
            model.SelectedProperties = selectedPropertyList.ToArray();
            model.SelectedSubjectID = subjectID;

            return View(model);

        }
        //This is a backup
        //public ActionResult ExportArchiveList(int activityID, List<ArchiveProperty> properties,int subjectID=-1)
        //{
        //    List<string> selectedPropertyList = new List<string>();
        //    if (properties != null)
        //    {
        //        foreach (var p in properties)
        //        {
        //            if (p.IsSelected)
        //            {
        //                //Debug.WriteLine("Property {0} is selected", p.Name);
        //                selectedPropertyList.Add(p.Name);
        //            }
        //        }
        //    }

        //    ViewBag.ActivityID = activityID;
        //    ViewBag.SubjectID = new SelectList(db.Subjects.Where(s => s.ActivityID == activityID), "ID", "Name");
            
        //    var propertInfos = GetArchiveProperties();
        //    List<ArchiveProperty> archPropList = new List<ArchiveProperty>();
        //    for (int i = 0; i < propertInfos.Count; i++)
        //    {
        //        archPropList.Add(new ArchiveProperty() { Id = i, Name = propertInfos[i].Name, LocalName = Translate(propertInfos[i].Name) });
        //    }

        //    ExportArchiveListModel model = new ExportArchiveListModel();
        //    var archives=db.Archives.Where(a => a.Subject.ActivityID == activityID);
        //    if (subjectID > 0)
        //    {
        //        archives = archives.Where(a => a.SubjectID == subjectID);
        //    }
        //    if (Roles.IsUserInRole("CountyAdmin"))
        //    {
        //        string countyCode = Utility.GetCountyCode();
        //        archives = archives.Where(a => a.CountyCode == countyCode);
        //    }
        //    model.Archives = archives;
        //    model.Properties = archPropList;
        //    model.SelectedProperties = selectedPropertyList.ToArray();
        //    model.SelectedSubjectID = subjectID;

        //    return View(model);

        //}



        public ActionResult Report(int activityID, int subjectID = -1, string[] selectedProperties = null)
        {
            var query = db.GetArchiveList(activityID).AsEnumerable();//db.Archives.Where(a => a.Subject.ActivityID == activityID);
            if (subjectID > 0)
            {
                query = query.Where(a => a.SubjectID == subjectID);
            }
            if (Roles.IsUserInRole("CountyAdmin"))
            {
                string countyCode = Utility.GetCountyCode();
                query = query.Where(a => a.CountyCode == countyCode);
            }
            //return CreateReport(query,new DoddleReport.Writers.ExcelReportWriter(), selectedProperties);
            Activity activity=db.Activities.Find(activityID);
            Subject subject=db.Subjects.Find(subjectID);
            string subTitle=string.Format("{0}:{1}",subject!=null?subject.Name:"",activity.Name);
            var report = Utility.CreateReport(query, selectedProperties,"Proposal List",subTitle);
            IReportWriter writer = new DoddleReport.Writers.ExcelReportWriter();
            return new ReportResult(report, writer, "application/vnd.ms-excel") { FileName = HttpUtility.UrlPathEncode("export.xls") }; 
        }


           

        public ActionResult ImportReviewFeedbacks(int subjectID)
        {
            ReviewFeedbackListModel model = new ReviewFeedbackListModel();
            model.SubjectID = subjectID;
            var subject = db.Subjects.Find(subjectID);
            model.ActivityName = subject.Activity.Name;
            model.ActivityID = subject.ActivityID;
            model.SubjectName = subject.Name;
            model.Feedbacks = ibl.GetFeedbacks(subjectID);

            return View(model);
        }

        [HttpPost]
        public ActionResult ImportReviewFeedbacks(int subjectID, HttpPostedFileBase file)
        {
            ReviewFeedbackListModel model = new ReviewFeedbackListModel();
            model.SubjectID = subjectID;
            var subject = db.Subjects.Find(subjectID);
            model.ActivityName = subject.Activity.Name;
            model.ActivityID = subject.ActivityID;
            model.SubjectName = subject.Name;

            // Verify that the user selected a file
            if (file != null && file.ContentLength > 0)
            {
                // extract only the fielname
                var fileName = Path.GetFileName(file.FileName);
                // store the file inside ~/App_Data/uploads folder
                var path = Path.Combine(Server.MapPath("~/App_Data/uploads"), fileName);
                file.SaveAs(path);


                var excel = new ExcelQueryFactory(path);
                //excel.FileName = ;
                excel.DatabaseEngine = DatabaseEngine.Ace;
                excel.AddMapping<FeedbackModel>(m => m.ArchiveSerialNumber, "ID");
                excel.AddMapping<FeedbackModel>(m => m.ProjectSN, "SN");
                excel.AddMapping<FeedbackModel>(m => m.ReviewFeedback, "Comments");
                excel.AddMapping<FeedbackModel>(m => m.Conclusion, "Conclusion");

                var feedbackList = from m in excel.Worksheet<FeedbackModel>()
                              select m;

                foreach (var f in feedbackList)
                {                    
                    ibl.AddFeedback(f,subjectID);                        
                }
            }

            model.Feedbacks = ibl.GetFeedbacks(subjectID);

            return View(model);//RedirectToAction("Index", new { activityID = subject.ActivityID });  
        }

        public ActionResult Feedback(string serialNumber)
        {
            ViewBag.ArchiveID=db.Archives.Where(a => a.SerialNumber==serialNumber).FirstOrDefault().ID;
            return View(ibl.ArchiveFeedback(serialNumber));
        }

        public ActionResult EditFeedback(string serialNumber)
        {
            return View(ibl.ArchiveFeedback(serialNumber));
        }

        [HttpPost]
        public ActionResult EditFeedback(FeedbackModel model)
        {
            if (!ibl.UpdateFeedback(model))
            {
                return View(model);
            }
            else
            {
                return RedirectToAction("Feedback", "Archive", new {serialNumber=model.ArchiveSerialNumber });
            }
        }

        public FileResult DownloadArchives(int activityID, int subjectID)
        {
            var archives = db.Archives.Where(a => a.SubjectID == subjectID && a.Subject.ActivityID == activityID);
            //create zip file
            string filename;
            string targetfile;
            using (ZipFile zip = new ZipFile(System.Text.Encoding.GetEncoding(936)))
            {
                foreach (var archive in archives)
                {
                    var path = Path.Combine(Server.MapPath("~/App_Data/Archives/"), activityID.ToString(), archive.ID.ToString());
                    if (Directory.Exists(path))
                    {
                        zip.AddDirectory(path, archive.Subject.Name + archive.SerialNumber + archive.TeacherName);
                    }
                }
                filename = Guid.NewGuid().ToString() + ".zip";
                if(!Directory.Exists(Server.MapPath("~/App_Data/zipfiles/")))
                {
                    Directory.CreateDirectory(Server.MapPath("~/App_Data/zipfiles/"));
                }
                targetfile = Path.Combine(Server.MapPath("~/App_Data/zipfiles/"), filename);
                zip.Save(targetfile);
                ViewBag.Filename = "~/App_Data/zipfiles/" + filename;
            }
            //return zip file url

            var subject = db.Subjects.Find(subjectID);
            string subjectName = "";
            if (subject != null)
            {
                subjectName = subject.Name;
            }
            else
            {
                subjectName = "Please choose topic and click preview.";
            }
            return File(targetfile, Utility.GetMimeType(Path.GetExtension(targetfile)), HttpUtility.UrlEncode(string.Format("{0}.zip",subjectName)));
        }

        [HttpPost]
        [Authorize(Roles = "Chair,Admin")]
        public ActionResult SetExpertGroup(int expertGroupID, List<ArchiveSelection> archives, int page=1, int round=-1)
        {
            //var x = archives;
            archives = archives.Where(a => a.IsSelected).ToList();
            foreach (var a in archives)
            {
                Archive archive = db.Archives.Find(a.ArchiveID);
                archive.ExpertGroupID = expertGroupID;
                archive.Status = (int)ArchiveStatus.UnderReview;
                db.SaveChanges();
            }
            int activityID = db.ExpertGroups.Find(expertGroupID).Subject.ActivityID;
            return RedirectToAction("Index", "Archive", new {ActivityID=activityID,Page=page,round=round });
        }

        [Authorize(Roles = "Chair")]
        public JsonResult Accept(int id, int accept, string SuggestedCategory, string ChairProposalFeedback, int round)
        {
            Archive archive = db.Archives.Find(id);
            bool sendemail = true;
            if (archive.Status > 3)
                sendemail = false;
            archive.Status = accept;
            archive.SuggestedCategory = SuggestedCategory;
            archive.ChairProposalFeedBack = ChairProposalFeedback.Replace("<", "&lt;").Replace(">", "&gt;").Replace("&lt;br/&gt;", "").Replace("\n", "<br/>");
            if(archive.PaperStatus==null)
                archive.PaperStatus= 0;
            db.Entry(archive).State = EntityState.Modified;
            db.SaveChanges();
            //string emailresult="";
            if(archive.StatusName==ArchiveStatus.Accepted && sendemail)
            {
                using (StreamReader reader = new StreamReader(Server.MapPath("~/App_Data/templates/proposalaccepted.txt")))
                {
                    string text = reader.ReadToEnd();
                    text = text.Replace("[ProposalID]", archive.CalculatedSerialNumber);
                    text = text.Replace("[Author]", String.Join(", ", archive.PAuthors.OrderBy(pa=>pa.Order).Select(pa=>pa.FirstName + " " + pa.LastName)));
                    text = text.Replace("[Title]", archive.ProjectTitle);
                    text = text.Replace("[Format]", archive.County.Name);
                    text = text.Replace("[AcceptedFormat]", archive.County1.Name);
                    //emailresult=
                    Utility.SendMail("Proposal Acceptance", text, archive.EMail);
                }
                
            }
            //return RedirectToAction("Index", new { activityid=archive.Subject.ActivityID});
            return Json(HttpContext.Request.Url.Scheme + "://" + HttpContext.Request.Url.Authority + Url.Action("Index", new { activityid = archive.Subject.ActivityID,round=round }), JsonRequestBehavior.AllowGet);
        }

        [Authorize(Roles = "Chair")]
        public ActionResult AcceptPaper(int id, int accept)
        {
            Archive archive = db.Archives.Find(id);
            if (accept < 5)
            {
                archive.PaperStatus = accept;
                db.Entry(archive).State = EntityState.Modified;
                db.SaveChanges();
            }
            return RedirectToAction("PaperIndex", new { activityid = archive.Subject.ActivityID });
        }

        //[Authorize(Roles = "Editor")]
        //public ActionResult AcceptPaperFinal(int id, int accept)
        //{
        //    Archive archive = db.Archives.Find(id);
        //    archive.PaperStatus = accept;
        //    db.Entry(archive).State = EntityState.Modified;
        //    db.SaveChanges();
        //    if (archive.PaperStatusName == ArchivePaperStatus.Accepted || archive.PaperStatusName == ArchivePaperStatus.RevisionNeeded)
        //    {
        //        using (StreamReader reader = new StreamReader(Server.MapPath("~/App_Data/templates/paperaccepted.txt")))
        //        {
        //            string text = reader.ReadToEnd();
        //            text = text.Replace("[Author]", String.Join(", ", archive.PAuthors.OrderBy(pa => pa.Order).Select(pa => pa.FirstName + " " + pa.LastName)));
        //            text = text.Replace("[Title]", archive.ProjectTitle);
        //            // text=text.Replace("[Authors]",);
        //            // text=text.Replace("[Topic]",);
        //            Utility.SendMail("Proceedings Paper Acceptance", text, archive.EMail);
        //        }
        //        //Utility.SendMail("Congratulations! Your paper is accepted!", "Congratulations! Your paper is accepted!", archive.EMail);
        //    }
        //    //else if (archive.PaperStatusName == ArchivePaperStatus.RevisionNeeded)
        //    //{
        //    //    Utility.SendMail("Revise paper", "Your need to be revised!", archive.EMail);
        //    //}
        //    return RedirectToAction("PaperIndex", new { activityid = archive.Subject.ActivityID });
        //}

        [Authorize(Roles = "Chair")]
        public JsonResult SaveChairReviewFeedback(int archiveid, string reviewfeedback, int accept)
        {
            Archive archive = db.Archives.Find(archiveid);
            archive.ChairPaperStatus = accept;
            archive.ReviewFeedback = reviewfeedback;
            db.Entry(archive).State = EntityState.Modified;
            db.SaveChanges();
            return Json(HttpContext.Request.Url.Scheme + "://" + HttpContext.Request.Url.Authority + Url.Action("PaperIndex", "Archive", new { activityid = archive.Subject.ActivityID}), JsonRequestBehavior.AllowGet);
        }

        [Authorize(Roles = "Chair")]
        public JsonResult SubmitChairReviewFeedback(int archiveid, string reviewfeedback, int accept)
        {

            Archive archive = db.Archives.Find(archiveid);
            archive.ChairPaperStatus = accept;
            //reject directly
            if (accept == 0)
                archive.PaperStatus = 5;
            else if (accept == 1)
                archive.PaperStatus = 3;
            else if (accept == 2)
                archive.PaperStatus = 4;

            archive.ReviewFeedback = reviewfeedback;
            db.Entry(archive).State = EntityState.Modified;
            db.SaveChanges();
            return Json(HttpContext.Request.Url.Scheme + "://" + HttpContext.Request.Url.Authority + Url.Action("PaperIndex", "Archive", new { activityid = archive.Subject.ActivityID }), JsonRequestBehavior.AllowGet);
        }

        [Authorize(Roles = "Editor")]
        [ValidateInput(false)]
        public JsonResult SaveEditorReviewFeedback(int archiveid, string reviewfeedback, int accept)
        {
            //if (User.IsInRole("Chair") && accept > 5)
            //    return RedirectToAction("Details", new { id = archiveid });
            Archive archive = db.Archives.Find(archiveid);
            archive.PaperStatus = accept;
            archive.EditorPaperReviewFeedback = reviewfeedback;
            db.Entry(archive).State = EntityState.Modified;
            db.SaveChanges();
            //if (archive.PaperStatusName == ArchivePaperStatus.Accepted || archive.PaperStatusName == ArchivePaperStatus.RevisionNeeded)
            //{
            //    using (StreamReader reader = new StreamReader(Server.MapPath("~/App_Data/templates/paperaccepted.txt")))
            //    {
            //        string text = reader.ReadToEnd();
            //        //text = text.Replace("[Author]", archive.Name);
            //        text = text.Replace("[Author]", String.Join(", ", archive.PAuthors.OrderBy(pa => pa.Order).Select(pa => pa.FirstName + " " + pa.LastName)));
            //        text = text.Replace("[Title]", archive.ProjectTitle);
            //        text = text.Replace("[Evaluation]", archive.EditorPaperReviewFeedback);
            //        // text=text.Replace("[Topic]",);
            //        Utility.SendMail("Proceedings Paper Acceptance", text, archive.EMail);
            //    }
            //}
            //return RedirectToAction("PaperIndex", new { activityid = archive.Subject.ActivityID });
            return Json(HttpContext.Request.Url.Scheme + "://" + HttpContext.Request.Url.Authority + Url.Action("PaperIndex", "Archive", new { activityid = archive.Subject.ActivityID }), JsonRequestBehavior.AllowGet);
        }

         [Authorize(Roles = "Editor")]
        public ActionResult SendPaperStatusNotificationEmail(int id)
        {
            Archive archive = db.Archives.Find(id);
            if (archive!=null) 
            {
                if (archive.PaperStatusName == ArchivePaperStatus.Rejected)
                {//.Accepted || archive.PaperStatusName == ArchivePaperStatus.RevisionNeeded) -- rejected email)
                    using (StreamReader reader = new StreamReader(Server.MapPath("~/App_Data/templates/paperaccepted.txt")))
                    {
                        string text = reader.ReadToEnd();
                        //text = text.Replace("[Author]", archive.Name);
                        text = text.Replace("[Author]", String.Join(", ", archive.PAuthors.OrderBy(pa => pa.Order).Select(pa => pa.FirstName + " " + pa.LastName)));
                        text = text.Replace("[Title]", archive.ProjectTitle);
                        string[] attachments = new string[2];
                        attachments[0] = Server.MapPath("~/Content/files/MRW-flyer-v2.pdf");
                        attachments[1] = Server.MapPath("~/Content/files/author_template-MRW.pdf");
                        Utility.SendMail("AECT-LKAOE 2015 Proceeding Paper Status Notification", text, archive.EMail, attachments);
                        ViewBag.EmailText = text;
                        ViewBag.Attachments = attachments;
                        ViewBag.EmailAddress = archive.EMail;
                    }
                }
                else if(archive.PaperStatusName==ArchivePaperStatus.Accepted)
                {
                    //Accepted email
                }
                else if (archive.PaperStatusName==ArchivePaperStatus.RevisionNeeded)
                {
                    //RevisionNeeded email
                }
            }

            ViewBag.ActivityId = archive.Subject.ActivityID;
            return View();
            //return RedirectToAction("PaperIndex", new { activityid = archive.Subject.ActivityID });
        }

        /// <summary>
        /// Start the paper review process. All submitted paper status will be set to underreview
        /// </summary>
        /// <param name="id">activityid</param>
        /// <returns></returns>
        [Authorize(Roles = "Chair")]
        [HttpPost]
        public JsonResult StartPaperReview(int activityid, int page = 1, int round=-1)
        {
            db.Archives.Where(a => a.Subject.ActivityID == activityid && a.PaperStatus == 1).ForEach(aa => aa.PaperStatus = 4);
            Activity activity=db.Activities.Find(activityid);
            db.SaveChanges();
            //Send Email to Reviewers and Chairs - Temporary disabled
            //string text = "";
            //using (StreamReader reader = new StreamReader(Server.MapPath("~/App_Data/templates/paperreminder.txt")))
            //{
            //    text = reader.ReadToEnd();
            //    text = text.Replace("[deadline]", activity.PaperReviewDueDate.Value.ToString());
            //    // text=text.Replace("[Authors]",);
            //    // text=text.Replace("[Topic]",);
            //}
            //var reviewers = db.ExpertJudges.ToList().ToExpertJudgeModelList();
            ////Utility.SendMail("Review Paper Reminder", "Review starts now. The deadline is " + activity.PaperReviewDueDate + ". Thank you! \n\r This is a system generated email.", "yehaisong@hotmail.com");
            //foreach (ExpertJudgeModel e in reviewers)
            //{
            //    Utility.SendMail("Review Paper Reminder", text, Membership.GetUser(e.SerialNumber).Email);
            //}
            ////send email to chairs
            //string[] chairnames = Roles.GetUsersInRole("Chair");
            //foreach (string un in chairnames)
            //{
            //    Utility.SendMail("Review Paper Reminder", text, Membership.GetUser(un).Email);
            //}

            //return RedirectToAction("PaperIndex", "Archive", new { ActivityID = activityid, Page = page });
            return Json(HttpContext.Request.Url.Scheme + "://" + HttpContext.Request.Url.Authority + Url.Action("PaperIndex", "Archive", new { ActivityID = activityid, Page = page, round=round }), JsonRequestBehavior.AllowGet);

        }
                
    }
}